package org.mathcloud.math.io.mml.content.generic;

import org.jdom.Element;
import org.mathcloud.math.core.common.factory.OperatorObjectFactory;
import org.mathcloud.math.core.common.factory.QuantityObjectFactory;
import org.mathcloud.math.core.common.operator.OperatorObject;
import org.mathcloud.math.core.common.quantity.ComplexNumber;
import org.mathcloud.math.core.common.quantity.MatrixObject;
import org.mathcloud.math.core.common.quantity.QuantityObject;
import org.mathcloud.math.core.common.quantity.RealNumber;
import org.mathcloud.math.io.mml.content.common.ApplyElementTranslator;
import org.mathcloud.math.io.mml.content.common.CIElementTranslator;
import org.mathcloud.math.io.mml.content.common.CNElementTranslator;
import org.mathcloud.math.io.mml.content.common.ElementFactory;
import org.mathcloud.math.io.mml.content.common.MatrixElementTranslator;

public class GenericElementFactory implements ElementFactory
{	
	public GenericElementFactory()
	{
		applyTranslator = null;
		cnTranslator = null;
		ciTranslator = null;
		operatorFactory = null;
		qobjectFactory = null;
	}
	
	@Override
	public Element getMathMLContent(OperatorObject arg0)
	{
		ApplyElementTranslator apply;
		if (applyTranslator!=null)
			apply = applyTranslator;
		else apply = new GenericApplyElementTranslator(); 
		return apply.getMathMLContent(arg0);
	}
	
	@Override
	public Element getMathMLContent(QuantityObject arg0, String type)
	{
		if (arg0.getSignature().isRealNumberSignature())
			return getMMLContent((RealNumber)arg0,type);
		else if (arg0.getSignature().isComplexNumberSignature())
			return getMMLContent((ComplexNumber)arg0,type);
		else if (arg0.getSignature().isMatrix())
			return getMMLContent((MatrixObject)arg0);
		else return null;
	}
	public Element getMMLContent(RealNumber arg0, String type)
	{
		if (cnTranslator!=null)
			return cnTranslator.getMathMLContent(arg0, type);
		else return new GenericCNElementTranslator().getMMLContent(arg0, type);
	}

	public Element getMMLContent(ComplexNumber arg0, String type)
	{
		if (cnTranslator!=null)
			return cnTranslator.getMathMLContent(arg0, type);
		else return new GenericCNElementTranslator().getMMLContent(arg0, type);
	}

	public Element getMMLContent(MatrixObject arg0)
	{
		if (matrixTranslator!=null)
			return matrixTranslator.getMathMLContent(arg0);
		else return new GenericMatrixElementTranslator().getMathMLContent(arg0);
	}

	@Override
	public QuantityObject getQuantityObject(Element arg0)
	{
		if (arg0.getName().equalsIgnoreCase("cn"))
		{
			if ((cnTranslator!=null)&&qobjectFactory!=null)
			{
				cnTranslator.setFactory(qobjectFactory);
				cnTranslator.setPrefix(prefix);
				cnTranslator.setRequestElement(arg0);			
				cnTranslator.translate();
				return cnTranslator.getResultObject();				
			}
			else return null;
		}
		else if (arg0.getName().equalsIgnoreCase("matrix"))
		{
			if (matrixTranslator!=null&&qobjectFactory!=null)
			{
				matrixTranslator.setFactory(qobjectFactory);
				matrixTranslator.setPrefix(prefix);
				matrixTranslator.setRequestElement(arg0);
				matrixTranslator.translate();
				return matrixTranslator.getResultObject();				
			}
			else return null;
		}
		else return null;
	}

	@Override
	public OperatorObject getOperatorObject(Element arg0)
	{
		if (arg0.getName().equalsIgnoreCase("apply"))
		{
			if (applyTranslator!=null&&operatorFactory!=null)
			{
				applyTranslator.setOperatorFactory(operatorFactory);
				applyTranslator.setPrefix(prefix);
				applyTranslator.setRequestElement(arg0);
				applyTranslator.translate();
				return applyTranslator.getResultObject();				
			}
			else return null;
		}
		else return null;
	}
	
	@Override
	public Element transform(Element arg0)
	{
		if (arg0.getName().equalsIgnoreCase("apply")&&applyTranslator!=null&&operatorFactory!=null)
		{			
			applyTranslator.setOperatorFactory(operatorFactory);
			applyTranslator.setElementFactory(this);
			applyTranslator.setPrefix(prefix);
			applyTranslator.setRequestElement(arg0);
			applyTranslator.translate();
			return applyTranslator.getResultElement();
		}
		else return arg0;
	}

	public OperatorObjectFactory getOperatorFactory()
	{
		return operatorFactory;
	}

	public void setOperatorFactory(OperatorObjectFactory operatorFactory)
	{
		this.operatorFactory = operatorFactory;
	}

	public QuantityObjectFactory getObjectFactory()
	{
		return qobjectFactory;
	}

	public void setObjectFactory(QuantityObjectFactory objectFactory)
	{
		this.qobjectFactory = objectFactory;
	}

	public String getPrefix()
	{
		return prefix;
	}

	public void setPrefix(String prefix)
	{
		this.prefix = prefix;
	}	
	
	public CNElementTranslator getCnTranslator()
	{
		return cnTranslator;
	}

	public void setCnTranslator(CNElementTranslator cnTranslator)
	{
		this.cnTranslator = cnTranslator;
	}

	public ApplyElementTranslator getApplyTranslator()
	{
		return applyTranslator;
	}

	public void setApplyTranslator(ApplyElementTranslator applyTranslator)
	{
		this.applyTranslator = applyTranslator;
	}

	public CIElementTranslator getCiTranslator()
	{
		return ciTranslator;
	}

	public void setCiTranslator(CIElementTranslator ciTranslator)
	{
		this.ciTranslator = ciTranslator;
	}

	public MatrixElementTranslator getMatrixTranslator()
	{
		return matrixTranslator;
	}

	public void setMatrixTranslator(MatrixElementTranslator matrixTranslator)
	{
		this.matrixTranslator = matrixTranslator;
	}	
	
	public static String namespaceURI = "http://www.w3.org/1998/Math/MathML";	
	private String prefix = "mml";
	
	protected CNElementTranslator cnTranslator;
	protected ApplyElementTranslator applyTranslator;
	protected CIElementTranslator ciTranslator;
	protected MatrixElementTranslator matrixTranslator;
	
	protected OperatorObjectFactory operatorFactory;
	protected QuantityObjectFactory qobjectFactory;
	
}
